#include <iostream>
#include <stdlib.h>
#include <math.h>

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/legacy/legacy.hpp"
#include "opencv2/legacy/compat.hpp"


using namespace std;
#ifdef _DEBUG
#pragma comment(lib, "..//opencv_lib//opencv_core240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_imgproc240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_highgui240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_flann240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_calib3d240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_contrib240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_features2d240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_legacy240d.lib")
#pragma comment(lib, "..//opencv_lib//opencv_nonfree240d.lib")
#else
#pragma comment(lib, "..//opencv_lib//opencv_core240.lib")
#pragma comment(lib, "..//opencv_lib//opencv_imgproc240.lib")
#endif

//by Huang, Haiqiao 5 Dec. 2009
int main(int argc, char** argv)
{
	cout << "Corner Detection OpenCV!"<<endl; 
	char* filename="5.bmp";
	//char* filename2="4.bmp";
	IplImage* imgRGB = cvLoadImage(filename); 
	IplImage* imgRGB2 = cvLoadImage(filename); 
	IplImage* imgGrey = cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE); 

	if (imgGrey==NULL){//image validation
		cout << "No valid image input."<<endl; 
		char c=getchar();
		return 1;
	} 
	int w=imgGrey->width;
	int h=imgGrey->height;

	IplImage* eig_image = cvCreateImage(cvSize(w, h),IPL_DEPTH_32F, 1);
	IplImage* temp_image = cvCreateImage(cvSize(w, h),IPL_DEPTH_32F, 1); 

	const int MAX_CORNERS = 140;//estimate a corner number
	CvPoint2D32f corners[MAX_CORNERS] = {0};// coordinates of corners
	//CvPoint2D32f* corners = new CvPoint2D32f[ MAX_CORNERS ]; //another method of declaring an array
	int corner_count = MAX_CORNERS; 
	double quality_level = 0.001;//threshold for the eigenvalues
	double min_distance = 5;//minimum distance between two corners
	int eig_block_size = 3;//window size
	int use_harris = false;//use 'harris method' or not

	//----------initial guess by cvGoodFeaturesToTrack---------------
	cvGoodFeaturesToTrack(imgGrey,
		eig_image,   // output                 
		temp_image,
		corners,
		&corner_count,
		quality_level,
		min_distance,
		NULL,
		eig_block_size,
		use_harris);


	int r=2; //rectangle size
	int lineWidth=1; // rectangle line width
	//-----draw good feature corners on the original RGB image---------
	for (int i=0;i<corner_count;i++){
		cvRectangle(imgRGB2, cvPoint(corners[i].x-r,corners[i].y-r), 
			cvPoint(corners[i].x+r,corners[i].y+r), cvScalar(255,0,0),lineWidth);
	}

	int half_win_size=3;//the window size will be 3+1+3=7
	int iteration=20;
	double epislon=0.1; 
	cvFindCornerSubPix(
		imgGrey,
		corners,
		corner_count,
		cvSize(half_win_size,half_win_size),
		cvSize(-1,-1),//no ignoring the neighbours of the center corner
		cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,iteration,epislon)
		);

	//------draw subpix corners on another original RGB image------------
	for (int i=0;i<corner_count;i++){
		cvRectangle(imgRGB, cvPoint(corners[i].x-r,corners[i].y-r), 
			cvPoint(corners[i].x+r,corners[i].y+r), cvScalar(0,255,255),lineWidth);
	}

	//to display a coordinate of the third corner
	cout<<"x="<<corners[2].x;
	cout<<",y="<<corners[2].y<<endl;

	cvNamedWindow("cvFindCornerSubPix", CV_WINDOW_AUTOSIZE );
	cvShowImage( "cvFindCornerSubPix", imgRGB );
	cvNamedWindow("cvGoodFeaturesToTrack", CV_WINDOW_AUTOSIZE );
	cvShowImage( "cvGoodFeaturesToTrack", imgRGB2 );


	cvWaitKey(0); 
	cvReleaseImage(&imgGrey);
	cvReleaseImage(&imgRGB);
	cvReleaseImage(&imgRGB2);
	cvDestroyWindow("cvGoodFeaturesToTrack");
	cvDestroyWindow("cvFindCornerSubPix");

	//char c=getchar();
	return 0;
}

